import { r2RequestClient } from '#/api/r2Request';
import { r2SliceRequestClient } from '#/api/r2SliceRequest';
import { requestClient } from '#/api/request';
import { generateNewFileName, splitFile } from '#/utils/index.ts';

interface GeneratePresigned {
  uploadUrl: string;
  ossObjectKey: string;
}
// R2预上传
export async function generatePresignedUrlApi(data) {
  return requestClient.post<GeneratePresigned>(
    '/material/backend/preupload',
    data,
  );
}

// 文件上传
export async function fileUploadR2(
  files: {
    bizType: 'CAR_IMAGE' | 'CAR_VIDEO' | 'USER_IMAGE';
    imageOssObjectKey: string;
    imageUrl: File | string;
  }[],
  parmsNames: {
    key: string;
    value: string;
  },
) {
  const keys: string[] = [];
  const promises: Promise<any>[] = [];
  // return Promise.all(
  //   files.map(async (file) => {
  //     const presignedData = await generatePresignedUrlApi();
  //     keys.push(presignedData.ossObjectKey);
  //     return r2RequestClient.put(presignedData.uploadUrl, file.raw, {
  //       withoutToken: true,
  //       headers: {
  //         'Content-Type': file.raw.type,
  //       },
  //     });
  //   }),
  // ).then(() => {
  //   return keys;
  // });
  for (const file of files) {
    if (file[parmsNames.key]) {
      keys.push(file[parmsNames.key]);
    } else {
      promises.push(
        generatePresignedUrlApi({ bizType: file.bizType }).then((res) => {
          keys.push(res.ossObjectKey);
          return r2RequestClient.put(
            res.uploadUrl,
            file[parmsNames.value].raw,
            {
              withoutToken: true,
              headers: {
                'Content-Type': (file[parmsNames.value] as File).raw.type,
                'Content-Disposition': `attachment; filename="${encodeURIComponent((file[parmsNames.value] as File).name)}"`,
              },
            },
          );
        }),
      );
    }
  }
  return Promise.all(promises).then(() => {
    return keys;
  });
}

// 文件分片上传获取uploadId
function fileUploadR2Part(contentType, fileName) {
  return requestClient.post('/material/backend/multi/apply', {
    contentType,
    contentDisposition: `attachment; filename=${encodeURIComponent(fileName)}`,
    bizType: 'CAR_VIDEO',
  });
}

// 文件分片预上传
function fileUploadR2PartPre(
  ossObjectKey: string,
  uploadId: string,
  partNum: number,
) {
  return requestClient.post(`/material/backend/multi/preupload`, {
    ossObjectKey,
    uploadId,
    partNum,
    bizType: 'CAR_VIDEO',
  });
}

// 文件分片上传
export function fileUploadR2PartUpload(
  file: File,
  progressData = null,
  isReUpload = false,
) {
  const promises: Promise<any>[] = [];
  const chunks = splitFile(file.raw);
  // 进度记录
  const progress = {
    total: chunks.length,
    uploaded: 0,
    ossObjectKey: '',
    uploadId: '',
    uploadedChunks: [],
    // 失败的分片
    failedChunks: [],
    etagList: [],
  };
  if (isReUpload) {
    progress.uploaded = progressData.uploaded;
    progress.ossObjectKey = progressData.ossObjectKey;
    progress.uploadId = progressData.uploadId;
    progress.uploadedChunks = progressData.uploadedChunks;
    progress.failedChunks = progressData.failedChunks;
    progress.etagList = progressData.etagList;
  }
  if (isReUpload) {
    if (progress.failedChunks.length === 0) {
      return new Promise((resolve, reject) => {
        resolve({ progress, promises: Promise.allSettled(promises) });
      });
    }
    progress.failedChunks.forEach((chunkIndex) => {
      const promis = new Promise((resolve, reject) => {
        fileUploadR2PartPre(
          progress.ossObjectKey,
          progress.uploadId,
          chunkIndex.partNum,
        )
          .then((res) => {
            return r2SliceRequestClient.put(
              res.uploadUrl,
              chunks[chunkIndex.partNum - 1].file,
              {
                withoutToken: true,
                headers: {
                  'Content-Type': 'application/octet-stream',
                },
              },
            );
          })
          .then(
            (res) => {
              progress.uploadedChunks.push({
                partNum: chunkIndex.partNum,
                etag: JSON.parse(res.headers.etag),
              });
              progress.uploaded++;
              progress.etagList.push(JSON.parse(res.headers.etag));
              progress.failedChunks = progress.failedChunks.filter(
                (item) => item.partNum !== chunkIndex.partNum,
              );
              resolve(true);
              // console.log(`上传进度: ${progress.uploaded}/${progress.total}`);
            },
            (error) => {
              // progress.failedChunks.push({
              //   partNum: chunkIndex,
              // });
              console.error(`分片 ${chunkIndex.partNum} 上传失败:`, error);
              reject(error);
            },
          )
          .catch((error) => {
            reject(error);
          });
      });
      promises.push(promis);
    });
    return new Promise((resolve, reject) => {
      resolve({ progress, promises: Promise.allSettled(promises) });
    });
  } else {
    return fileUploadR2Part(
      file.raw.type,
      generateNewFileName(file.raw.name),
    ).then((res) => {
      progress.ossObjectKey = res.ossObjectKey;
      progress.uploadId = res.uploadId;
      chunks.forEach((chunk, index) => {
        const promis = new Promise((resolve, reject) => {
          fileUploadR2PartPre(res.ossObjectKey, res.uploadId, index + 1)
            .then((res) => {
              return r2SliceRequestClient.put(res.uploadUrl, chunk.file, {
                withoutToken: true,
                headers: {
                  'Content-Type': 'application/octet-stream',
                },
              });
            })
            .then(
              (res) => {
                progress.uploadedChunks.push({
                  partNum: index + 1,
                  etag: JSON.parse(res.headers.etag),
                });
                progress.uploaded++;
                progress.etagList.push(JSON.parse(res.headers.etag));
                resolve(true);
                // console.log(`上传进度: ${progress.uploaded}/${progress.total}`);
              },
              (error) => {
                progress.failedChunks.push({
                  partNum: index + 1,
                });
                console.error(`分片 ${index + 1} 上传失败:`, error);
                reject(error);
              },
            )
            .catch((error) => {
              reject(error);
            });
        });
        promises.push(promis);
      });
      return new Promise((resolve, reject) => {
        resolve({ progress, promises: Promise.allSettled(promises) });
      });
    });
  }
}

// 文件分片上传完成
export function fileUploadR2PartComplete(
  ossObjectKey: string,
  uploadId: string,
  etagList: string[],
) {
  return requestClient.post(`/material/backend/multi/cpmmpleteUpload`, {
    ossObjectKey,
    uploadId,
    etagList,
    bizType: 'CAR_VIDEO',
  });
}

// 根据ossObjectKey获取下载地址
export async function getDownloadUrlApi(ossObjectKey: string) {
  return requestClient.get<string>('/material/getDownloadUrl', {
    ossObjectKey,
  });
}
